home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / fontSelect.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  24KB  |  921 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/StringDefs.h>
  16. #include <X11/Intrinsic.h>
  17. #include <X11/Shell.h>
  18. #include <X11/Xaw/Form.h>
  19. #include <X11/Xaw/Paned.h>
  20. #include <X11/Xaw/List.h>
  21. #include <X11/Xaw/AsciiText.h>
  22. #include <X11/Xaw/Command.h>
  23. #include <X11/Xaw/Viewport.h>
  24. #include <X11/Xos.h>
  25. #include <math.h>
  26. #include <stdio.h>
  27.  
  28. /*
  29. **  swiped from X11/Xfuncproto.h
  30. **   since qsort() may or may not be defined with a constant sub-function
  31. */
  32. #ifndef _Xconst
  33. #if __STDC__ || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&4)
  34. #define _Xconst const
  35. #else
  36. #define _Xconst
  37. #endif
  38. #endif /* _Xconst */
  39.  
  40. #ifndef NOSTDHDRS
  41. #include <stdlib.h>
  42. #include <unistd.h>
  43. #endif
  44.  
  45. #include "xpaint.h"
  46. #include "misc.h"
  47. #include "ops.h"
  48.  
  49. typedef struct {
  50.     char    *fontFamily;
  51.     char    *registry;
  52.     char    *foundry;
  53.     char    *weight;
  54.     char    *slant;
  55.     char    *setWidth;
  56.     char    *points;
  57.     char    *spacing;
  58.     Boolean    forcePoint;
  59. } FontName;
  60.  
  61. static Boolean    haveScalable = False;
  62.  
  63. typedef struct StringList_s {
  64.     char            *str;
  65.     struct StringList_s    *next;
  66. } StringList;
  67.  
  68. typedef struct {
  69.     int        number;
  70.     FontName    *names;
  71.     char        **namesStorage;
  72.     Widget        text, paint;
  73.     Widget        family, weight, point, spacing;
  74.     Widget        expect, pointSelect;
  75.     Widget        fontName;
  76.     Boolean        expectFlag;
  77. } arg_t;
  78.  
  79.  
  80. static struct shortFamily_s {
  81.     char    *name;
  82.     char    *family, *registry, *foundry;
  83. } shortFamily[128];
  84. static int shortFamilyNum = 0;
  85.  
  86. static arg_t    *theArg = NULL;
  87.  
  88. static char    *getShortFamily(char *family, char *foundry, char *registry)
  89. {
  90.     int    i;
  91.  
  92.     for (i = 0; i < shortFamilyNum; i++) {
  93.         if (strcmp(shortFamily[i].family, family) == 0 &&
  94.             strcmp(shortFamily[i].foundry, foundry) == 0 &&
  95.             strcmp(shortFamily[i].registry, registry) == 0)
  96.             return shortFamily[i].name;
  97.     }
  98.     return "UNKNOWN";
  99. }
  100.  
  101. static void    makeShortFamily(char *family, char *foundry, char *registry)
  102. {
  103.     char    buf[256];
  104.  
  105.     if (strcmp(getShortFamily(family, foundry, registry), "UNKNOWN") != 0)
  106.         return;
  107.     
  108.     shortFamily[shortFamilyNum].family   = family;
  109.     shortFamily[shortFamilyNum].foundry  = foundry;
  110.     shortFamily[shortFamilyNum].registry = registry;
  111.     sprintf(buf, "%s (%s,%s)", family, foundry, registry);
  112.     shortFamily[shortFamilyNum].name     = XtNewString(buf);
  113.     shortFamilyNum++;
  114. }
  115.  
  116. static struct shortSizes_s {
  117.     char    *name;
  118.     char    *weight;
  119.     char    *slant;
  120.     char    *setWidth;
  121.     char    *serif;
  122. } shortSizes[128];
  123. static int shortSizesNum = 0;
  124.  
  125. static char    *getShortName(char *weight, char *slant, char *setWidth, char *serif)
  126. {
  127.     int    i;
  128.     for (i = 0; i < shortSizesNum; i++) {
  129.         if (strcmp(shortSizes[i].weight, weight) == 0 &&
  130.             strcmp(shortSizes[i].slant, slant) == 0 &&
  131.             strcmp(shortSizes[i].setWidth, setWidth) == 0 &&
  132.             strcmp(shortSizes[i].serif, serif) == 0)
  133.             return shortSizes[i].name;
  134.     }
  135.     return "UNKNOWN";
  136. }
  137.  
  138. static void    makeShortName(char *weight, char *slant, char *setWidth, char *serif)
  139. {
  140.     char     *weStr, *slStr, *swStr, *seStr;
  141.     char    *cp, buf[128];
  142.  
  143.     if (strcmp(getShortName(weight, slant, setWidth, serif), "UNKNOWN") != 0)
  144.         return;
  145.  
  146.     shortSizes[shortSizesNum].weight = weight;
  147.     shortSizes[shortSizesNum].slant = slant;
  148.     shortSizes[shortSizesNum].setWidth = setWidth;
  149.     shortSizes[shortSizesNum].serif = serif;
  150.  
  151.     if (*weight == '\0')
  152.         weStr = NULL;
  153.     else if (strcmp(weight, "medium") == 0)
  154.         weStr = "";
  155.     else if (strcmp(weight, "bold") == 0)
  156.         weStr = "Bold";
  157.     else
  158.         weStr = weight;
  159.     
  160.     if (*slant == '\0')
  161.         slStr = NULL;
  162.     else if (*slant == 'r')
  163.         slStr = "";
  164.     else if (*slant == 'i')
  165.         slStr = "Italic";
  166.     else if (*slant == 'o')
  167.         slStr = "Oblique";
  168.     else
  169.         slStr = slant;
  170.  
  171.     if (*setWidth == '\0')
  172.         swStr = NULL;
  173.     else if (strcmp(setWidth, "normal") == 0)
  174.         swStr = "";
  175.     else if (strcmp(setWidth, "semicondensed") == 0)
  176.         swStr = "Condensed";
  177.     else
  178.         swStr = setWidth;
  179.  
  180.     if (*serif == '\0')
  181.         seStr = NULL;
  182.     else if (strcmp(serif, "sans") == 0)
  183.         seStr = "";
  184.     else
  185.         seStr = serif;
  186.  
  187.     if (weStr == NULL && slStr == NULL && swStr == NULL && seStr == NULL) {
  188.         shortSizes[shortSizesNum++].name = "Unspecified";
  189.         return;
  190.     }
  191.     if (weStr == NULL) weStr = "";
  192.     if (slStr == NULL) slStr = "";
  193.     if (swStr == NULL) swStr = "";
  194.     if (seStr == NULL) seStr = "";
  195.  
  196.     if (*weStr == '\0' && *slStr == '\0' && *swStr == '\0' && *seStr == '\0') {
  197.         shortSizes[shortSizesNum++].name = "Normal";
  198.         return;
  199.     }
  200.  
  201.     /*
  202.     ** Make the string, eat the leading and trailing white space.
  203.     */
  204.     sprintf(buf, "%s %s %s %s", weStr, slStr, swStr, seStr);
  205.     for (cp = buf + strlen(buf) - 1; *cp == ' '; cp--)
  206.         ;
  207.     *++cp = '\0';
  208.     for (cp = buf; *cp == ' '; cp++)
  209.         ;
  210.     shortSizes[shortSizesNum++].name = XtNewString(cp);
  211. }
  212.  
  213. static FontName    *getSettings(arg_t *arg)
  214. {
  215.     static char        pointBuf[20];
  216.     static FontName        name;
  217.     XawListReturnStruct    *item;
  218.     int            i;
  219.  
  220.     name.fontFamily = NULL;
  221.     name.weight     = NULL;
  222.     name.slant      = NULL;
  223.     name.setWidth   = NULL;
  224.     name.points     = NULL;
  225.     name.spacing    = NULL;
  226.     name.foundry    = NULL;
  227.     name.registry   = NULL;
  228.     name.forcePoint = False;
  229.  
  230.     if ((item = XawListShowCurrent(arg->family))->list_index != XAW_LIST_NONE) {
  231.         for (i = 0; i < XtNumber(shortFamily); i++) {
  232.             if (strcmp(item->string, shortFamily[i].name) == 0) {
  233.                 name.fontFamily = shortFamily[i].family;
  234.                 name.registry = shortFamily[i].registry;
  235.                 name.foundry = shortFamily[i].foundry;
  236.                 break;
  237.             }
  238.         }
  239.         XtFree((XtPointer)item);
  240.     }
  241.     if ((item = XawListShowCurrent(arg->point))->list_index != XAW_LIST_NONE) {
  242.         float    ps = atof(item->string);
  243.         if (ps < 0.1 && haveScalable) {
  244.             String    str;
  245.             name.forcePoint = True;
  246.             XtVaGetValues(arg->pointSelect, XtNstring, &str, NULL);
  247.             ps = atof(str);
  248.             if (ps < 0.1) {
  249.                 ps = 12.0;
  250.                 XtVaSetValues(arg->pointSelect, XtNstring, "12", NULL);
  251.             }
  252.         }
  253.         sprintf(pointBuf,"%d",(int)(ps * 10.0));
  254.         name.points = pointBuf;
  255.         XtFree((XtPointer)item);
  256.     }
  257.     if ((item = XawListShowCurrent(arg->weight))->list_index != XAW_LIST_NONE) {
  258.         for (i = 0; i < XtNumber(shortSizes); i++) {
  259.             if (strcmp(item->string, shortSizes[i].name) == 0) {
  260.                 name.weight = shortSizes[i].weight;
  261.                 name.slant = shortSizes[i].slant;
  262.                 name.setWidth = shortSizes[i].setWidth;
  263.                 break;
  264.             }
  265.         }
  266.         XtFree((XtPointer)item);
  267.     }
  268.     if ((item = XawListShowCurrent(arg->spacing))->list_index != XAW_LIST_NONE) {
  269.         if (strcmp(item->string, "Fixed") == 0)
  270.             name.spacing = "m";
  271.         else if (strcmp(item->string, "Variable") == 0)
  272.             name.spacing = "p";
  273.         else if (strcmp(item->string, "Cell") == 0)
  274.             name.spacing = "c";
  275.         else
  276.             name.spacing = item->string;
  277.         XtFree((XtPointer)item);
  278.     }
  279.  
  280.     return &name;
  281. }
  282.  
  283. static int strqsortcmp(char **a, char **b)
  284.     return strcmp(*a, *b);
  285. }
  286.  
  287. static int valqsortcmp(char **a, char **b)
  288.     float    fa = atof(*a);
  289.     float    fb = atof(*b);
  290.     if (fa == fb)
  291.         return 0;
  292.     if (fa < fb)
  293.         return -1;
  294.     return 1;
  295. }
  296.  
  297. static void cleanLists(arg_t *arg)
  298. {
  299.     String    *strs;
  300.     int    num;
  301.  
  302.     XtVaGetValues(arg->spacing, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  303.     if (strs != NULL && num != 0) XtFree((XtPointer)strs);
  304.     XtVaGetValues(arg->family, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  305.     if (strs != NULL && num != 0) XtFree((XtPointer)strs);
  306.     XtVaGetValues(arg->weight, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  307.     if (strs != NULL && num != 0) XtFree((XtPointer)strs);
  308.     XtVaGetValues(arg->point, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  309.     if (strs != NULL && num != 0) {
  310.         int    i;
  311.         for (i = 0; i < num; i++)
  312.             XtFree((XtPointer)strs[i]);
  313.         XtFree((XtPointer)strs);
  314.     }
  315. }
  316.  
  317. static void    match(arg_t *arg)
  318. {
  319.     static int    firstTime = True;
  320.     int        i;
  321.     int        count = 0;
  322.     char        *nm;
  323.     FontName    *cur = arg->names, *last = NULL;
  324.     FontName    *set = getSettings(arg);
  325.     StringList    *familyList = NULL, *pointList = NULL;
  326.     StringList    *weightList = NULL, *spacingList = NULL;
  327.     int        familyListLen = 0, pointListLen = 0;
  328.     int        weightListLen = 0, spacingListLen = 0;
  329.     StringList    *curStr, *nxtStr;
  330.     String        *list;
  331.  
  332.     if (firstTime)
  333.         firstTime = False;
  334.     else
  335.         cleanLists(arg);
  336.  
  337.     for (i = 0; i < arg->number; i++, cur++) {
  338.  
  339. #define TEST(f)    if (set->f != NULL && strcmp(set->f, cur->f) != 0) continue
  340.         TEST(fontFamily);
  341.         TEST(foundry);
  342.         TEST(registry);
  343.         TEST(weight);
  344.         TEST(slant);
  345.         TEST(setWidth);
  346.         if (set->forcePoint) {
  347.             if (strcmp(cur->points, "0") != 0) continue;
  348.         } else {
  349.             TEST(points);
  350.         }
  351.         TEST(spacing);
  352. #undef TEST
  353.  
  354.         /*
  355.         **  Add the family name
  356.         */
  357.         switch (*cur->spacing) {
  358.         case 'm': nm = "Fixed";        break;
  359.         case 'p': nm = "Variable";    break;
  360.         case 'c': nm = "Cell";        break;
  361.         default:  nm = cur->spacing;    break;
  362.         }
  363.         for (curStr = spacingList; curStr != NULL; curStr = curStr->next) {
  364.             if (strcmp(curStr->str, nm) == 0)
  365.                 break;
  366.         }
  367.         if (curStr == NULL) {
  368.             curStr = XtNew(StringList);
  369.             curStr->next = spacingList;
  370.             curStr->str = nm;
  371.             spacingList = curStr;
  372.             spacingListLen++;
  373.         }
  374.  
  375.         /*
  376.         **  Add the family name
  377.         */
  378.         nm = getShortFamily(cur->fontFamily, cur->foundry, cur->registry);
  379.         for (curStr = familyList; curStr != NULL; curStr = curStr->next) {
  380.             if (strcmp(curStr->str, nm) == 0)
  381.                 break;
  382.         }
  383.         if (curStr == NULL) {
  384.             curStr = XtNew(StringList);
  385.             curStr->next = familyList;
  386.             curStr->str = nm;
  387.             familyList = curStr;
  388.             familyListLen++;
  389.         }
  390.  
  391.         /*
  392.         **  Add the width info
  393.         */
  394.         nm = getShortName(cur->weight, cur->slant, cur->setWidth, "");
  395.         for (curStr = weightList; curStr != NULL; curStr = curStr->next) {
  396.             if (strcmp(curStr->str, nm) == 0)
  397.                 break;
  398.         }
  399.         if (curStr == NULL) {
  400.             curStr = XtNew(StringList);
  401.             curStr->next = weightList;
  402.             curStr->str = nm;
  403.             weightList = curStr;
  404.             weightListLen++;
  405.         }
  406.  
  407.         /*
  408.         **  Add the point size
  409.         */
  410.         for (curStr = pointList; curStr != NULL; curStr = curStr->next) {
  411.             if ((int)(atof(curStr->str)*10.0) == atoi(cur->points)) 
  412.                 break;
  413.         }
  414.         if (curStr == NULL) {
  415.             char    buf[14];
  416.             int    p = atoi(cur->points);
  417.  
  418.             curStr = XtNew(StringList);
  419.             curStr->next = pointList;
  420.             if (p % 10 == 0) {
  421.                 sprintf(buf,"%d   ", p / 10);
  422.             } else {
  423.                 sprintf(buf,"%d.%d   ", p / 10, p % 10);
  424.             }
  425.             curStr->str = XtNewString(buf);
  426.             pointList = curStr;
  427.             pointListLen++;
  428.         }
  429.  
  430.         count++;
  431.         last = cur;
  432.     }
  433.  
  434.     if (count == 1 && last != NULL) {
  435.         char        buf[512];
  436.         XFontStruct    *info;
  437.         sprintf(buf, "-%s-%s-%s-%s-%s-*-*-%s-*-*-%s-*-%s-*",
  438.                 last->foundry,
  439.                 last->fontFamily,
  440.                 last->weight == NULL ? "" : last->weight,
  441.                 last->slant == NULL ? "" : last->slant,
  442.                 last->setWidth == NULL ? "" : last->setWidth,
  443.                 set->forcePoint ? set->points : last->points,
  444.                 last->spacing,
  445.                 last->registry);
  446.  
  447.         if ((info = XLoadQueryFont(XtDisplay(arg->text), buf)) != NULL) {
  448.             XtVaSetValues(arg->text, 
  449.                 XtNfont, info,
  450.                 XtNstring, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlmnopqrstuvwxyz0123456789", 
  451.                 NULL);
  452.             XtVaSetValues(arg->fontName, XtNstring, buf, NULL);
  453.         }
  454.     } else {
  455.         XtVaSetValues(arg->text, XtNstring, "", NULL);
  456.         XtVaSetValues(arg->fontName, XtNstring, "", NULL);
  457.     }
  458.  
  459.     /*
  460.     **  Set the widgets
  461.     */
  462.  
  463.     list = (String *)XtCalloc(spacingListLen + 1, sizeof(String));
  464.     for (i = 0, curStr = spacingList; curStr != NULL; curStr = curStr->next, i++) 
  465.         list[i] = curStr->str;
  466.     qsort(list, i, sizeof(String), (int (*)(_Xconst void *,_Xconst void *))strqsortcmp);
  467.     XawListChange(arg->spacing, list, spacingListLen, 0, True);
  468.     if (set->spacing)
  469.         XawListHighlight(arg->spacing, 0);
  470.  
  471.     list = (String *)XtCalloc(familyListLen + 1, sizeof(String));
  472.     for (i = 0, curStr = familyList; curStr != NULL; curStr = curStr->next, i++) 
  473.         list[i] = curStr->str;
  474.     qsort(list, i, sizeof(String), (int (*)(_Xconst void *,_Xconst void *))strqsortcmp);
  475.     XawListChange(arg->family, list, familyListLen, 0, True);
  476.     if (set->fontFamily)
  477.         XawListHighlight(arg->family, 0);
  478.     
  479.     list = (String *)XtCalloc(weightListLen + 1, sizeof(String));
  480.     for (i = 0, curStr = weightList; curStr != NULL; curStr = curStr->next, i++) 
  481.         list[i] = curStr->str;
  482.     qsort(list, i, sizeof(String), (int (*)(_Xconst void *,_Xconst void *))strqsortcmp);
  483.     XawListChange(arg->weight, list, weightListLen, 0, True);
  484.     if (set->weight)
  485.         XawListHighlight(arg->weight, 0);
  486.  
  487.     list = (String *)XtCalloc(pointListLen + 1, sizeof(String));
  488.     for (i = 0, curStr = pointList; curStr != NULL; curStr = curStr->next, i++) 
  489.         list[i] = curStr->str;
  490.     qsort(list, i, sizeof(String), (int (*)(_Xconst void *,_Xconst void *))valqsortcmp);
  491.     XawListChange(arg->point, list, pointListLen, 0, True);
  492.     if (set->points)
  493.         XawListHighlight(arg->point, 0);
  494.  
  495.     /*
  496.     **  Clean up
  497.     */
  498.     for (curStr = spacingList; curStr != NULL; curStr = nxtStr) {
  499.         nxtStr = curStr->next;
  500.         XtFree((XtPointer)curStr);
  501.     }
  502.     for (curStr = familyList; curStr != NULL; curStr = nxtStr) {
  503.         nxtStr = curStr->next;
  504.         XtFree((XtPointer)curStr);
  505.     }
  506.     for (curStr = weightList; curStr != NULL; curStr = nxtStr) {
  507.         nxtStr = curStr->next;
  508.         XtFree((XtPointer)curStr);
  509.     }
  510.     for (curStr = pointList; curStr != NULL; curStr = nxtStr) {
  511.         nxtStr = curStr->next;
  512.         XtFree((XtPointer)curStr);
  513.     }
  514. }
  515.  
  516. static FontName    *chop(int *number, char **names)
  517. {
  518.     int        i, j, count = 0;
  519.     FontName    *n = (FontName*)XtCalloc(*number, sizeof(FontName));
  520.  
  521.     if (n == NULL)
  522.         return NULL;
  523.  
  524. #define NEXT(p) {     char    *np;                \
  525.             if ((np = strchr(p, '-')) == NULL)    \
  526.                 continue;            \
  527.             *np++ = '\0';                \
  528.             p = np;                    \
  529.         }
  530.  
  531.     for (i = 0; i < *number; i++) {
  532.         char        *cp = names[i];
  533.         FontName    *cur = &n[count];
  534.  
  535.         NEXT(cp);    /* foundry */
  536.         cur->foundry = cp;
  537.         NEXT(cp);    /* font family */
  538.         cur->fontFamily = cp;
  539.         NEXT(cp);    /* weight */
  540.         cur->weight = cp;
  541.         NEXT(cp);    /* slant */
  542.         cur->slant = cp;
  543.         NEXT(cp);    /* set width */
  544.         cur->setWidth = cp;
  545.         NEXT(cp);    /* NULL */
  546.         NEXT(cp);    /* pixels */
  547.         NEXT(cp);    /* point size */
  548.         cur->points = cp;
  549.         NEXT(cp);    /* horizontal resolution */
  550.         NEXT(cp);    /* vertical resolution */
  551.         NEXT(cp);    /* spacing */
  552.         cur->spacing = cp;
  553.         NEXT(cp);    /* average width */
  554.         NEXT(cp);    /* character set */
  555.         cur->registry = cp;
  556.         NEXT(cp);    /* character class */
  557.  
  558.         /*
  559.         **  Check to make sure that this is a unique font
  560.         **   from the rest of the set.
  561.         */
  562.         for (j = 0; j < count; j++) {
  563.             if (strcmp(cur->fontFamily, n[j].fontFamily) == 0 && 
  564.                 strcmp(cur->weight, n[j].weight) == 0 && 
  565.                 strcmp(cur->slant, n[j].slant) == 0 && 
  566.                 strcmp(cur->setWidth, n[j].setWidth) == 0 && 
  567.                 strcmp(cur->points, n[j].points) == 0 && 
  568.                 strcmp(cur->spacing, n[j].spacing) == 0)
  569.                 break;
  570.         }
  571.         makeShortName(cur->weight, cur->slant, cur->setWidth, "");
  572.         makeShortFamily(cur->fontFamily, cur->foundry, cur->registry);
  573.         if (j != count)
  574.             continue;
  575.         if (atoi(cur->points) == 0)
  576.             haveScalable = True;
  577.         count++;
  578.     }
  579. #undef NEXT
  580.  
  581.     *number = count;
  582.     return n;
  583. }
  584.  
  585. static void applySetCallback(Widget paint, Arg *xarg)
  586. {
  587.     XtSetValues(paint, xarg, 1);
  588.     FontChanged(paint);
  589. }
  590. static void applyCallback(Widget w, XtPointer argArg, XtPointer junk)
  591. {
  592.     arg_t        *arg = (arg_t *)argArg;
  593.     XFontStruct     *info;
  594.     Arg        xarg;
  595.  
  596.     XtVaGetValues(arg->text, XtNfont, &info, NULL);
  597.  
  598.     XtSetArg(xarg, XtNfont, info);
  599.     OperationAddArg(xarg);
  600.     GraphicAll((GraphicAllProc)applySetCallback, (void*)&xarg);
  601. }
  602. static void closeCallback(Widget w, XtPointer argArg, XtPointer junk)
  603. {
  604.     arg_t    *arg = (arg_t *)argArg;
  605.  
  606.     XtPopdown(GetShell(arg->family));
  607. }
  608. static void okCallback(Widget w, XtPointer argArg, XtPointer junk)
  609. {
  610.     applyCallback(w, argArg, junk);
  611.     closeCallback(w, argArg, junk);
  612. }
  613. static void listCallback(Widget w, XtPointer argArg, XtPointer junk)
  614. {
  615.     arg_t    *arg = (arg_t *)argArg;
  616.     arg->expectFlag = True;
  617.     arg->expect = None;
  618.     match(arg);
  619. }
  620. static void expectCallback(Widget w, XtPointer argArg, XEvent *event, Boolean *junk)
  621. {
  622.     arg_t    *arg = (arg_t*)argArg;
  623.  
  624.     if (event->type == ButtonRelease) {
  625.         if (arg->expect != None)
  626.             match(arg);
  627.         arg->expect = None;
  628.         arg->expectFlag = False;
  629.     } else if (arg->expectFlag == False) {
  630.         arg->expect = w;
  631.     }
  632. }
  633. static void pointSizeAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
  634. {
  635.     /* XXX */    
  636.     if (theArg == NULL)
  637.         return;
  638.  
  639.     if (!XtIsManaged(theArg->pointSelect))
  640.         return;
  641.     match(theArg);
  642. }
  643.  
  644. void FontSelect(Widget w, Widget paint)
  645. {
  646.     static XtActionsRec    pointAct = { "point-size-ok", (XtActionProc)pointSizeAction };
  647.     static Widget    shell = None;
  648.     Widget        pane, form, selectLabel, form2;
  649.     Widget        applyButton, okButton, doneButton, vport, label;
  650.     arg_t        *arg = XtNew(arg_t);
  651.  
  652.     if (shell != None) {
  653.         XtPopup(shell, XtGrabNone);
  654.         XMapRaised(XtDisplay(shell), XtWindow(shell));
  655.         return;
  656.     }
  657.  
  658.     StateSetBusyWatch(True);
  659.  
  660.     shell = XtVaCreatePopupShell("fontSelect",
  661.             topLevelShellWidgetClass, GetToplevel(w),
  662.             NULL);
  663.  
  664.     pane = XtVaCreateManagedWidget("pane",
  665.             panedWidgetClass, shell,
  666.             XtNborderWidth, 0,
  667.             NULL);
  668.  
  669.     label = XtVaCreateManagedWidget("title",
  670.             labelWidgetClass, pane,
  671.             XtNlabel, "Select the font properties you wish",
  672.             XtNborderWidth, 0,
  673.             XtNshowGrip, False,
  674.             NULL);
  675.  
  676.     form = XtVaCreateManagedWidget("form",
  677.             formWidgetClass, pane,
  678.             XtNborderWidth, 0,
  679.             NULL);
  680.  
  681.     /*
  682.     **  lists of items to select
  683.     */
  684.     label = XtVaCreateManagedWidget("spacingLabel",
  685.             labelWidgetClass, form,
  686.             XtNborderWidth, 0,
  687.             XtNtop, XtChainTop,
  688.             XtNbottom, XtChainTop,
  689.             NULL);
  690.     vport = XtVaCreateManagedWidget("vport",
  691.             viewportWidgetClass, form,
  692.             XtNuseBottom, True,
  693.             XtNuseRight, True,
  694.             XtNforceBars, True,
  695.             XtNallowHoriz, False,
  696.             XtNallowVert, True,
  697.             XtNfromVert, label,
  698.             XtNtop, XtChainTop,
  699.             NULL);
  700.     arg->spacing = XtVaCreateManagedWidget("spacing",
  701.                 listWidgetClass, vport,
  702.                 XtNverticalList, True,
  703.                 XtNforceColumns, True,
  704.                 XtNdefaultColumns, 1,
  705.                 XtNnumberStrings, 0,
  706.                 NULL);
  707.     label = XtVaCreateManagedWidget("familyLabel",
  708.             labelWidgetClass, form,
  709.             XtNborderWidth, 0,
  710.             XtNfromHoriz, vport,
  711.             XtNtop, XtChainTop,
  712.             XtNbottom, XtChainTop,
  713.             NULL);
  714.     vport = XtVaCreateManagedWidget("vport",
  715.             viewportWidgetClass, form,
  716.             XtNuseBottom, True,
  717.             XtNuseRight, True,
  718.             XtNforceBars, True,
  719.             XtNallowHoriz, False,
  720.             XtNallowVert, True,
  721.             XtNfromVert, label,
  722.             XtNfromHoriz, vport,
  723.             XtNtop, XtChainTop,
  724.             NULL);
  725.     arg->family = XtVaCreateManagedWidget("font",
  726.                 listWidgetClass, vport,
  727.                 XtNverticalList, True,
  728.                 XtNforceColumns, True,
  729.                 XtNdefaultColumns, 1,
  730.                 XtNnumberStrings, 0,
  731.                 NULL);
  732.     label = XtVaCreateManagedWidget("weightLabel",
  733.             labelWidgetClass, form,
  734.             XtNborderWidth, 0,
  735.             XtNfromHoriz, vport,
  736.             XtNtop, XtChainTop,
  737.             XtNbottom, XtChainTop,
  738.             NULL);
  739.     vport = XtVaCreateManagedWidget("vport",
  740.             viewportWidgetClass, form,
  741.             XtNuseBottom, True,
  742.             XtNuseRight, True,
  743.             XtNforceBars, True,
  744.             XtNallowHoriz, False,
  745.             XtNallowVert, True,
  746.             XtNfromHoriz, vport,
  747.             XtNfromVert, label,
  748.             XtNtop, XtChainTop,
  749.             NULL);
  750.     arg->weight = XtVaCreateManagedWidget("weight",
  751.                 listWidgetClass, vport,
  752.                 XtNverticalList, True,
  753.                 XtNforceColumns, True,
  754.                 XtNdefaultColumns, 1,
  755.                 XtNnumberStrings, 0,
  756.                 NULL);
  757.     label = XtVaCreateManagedWidget("pointLabel",
  758.             labelWidgetClass, form,
  759.             XtNborderWidth, 0,
  760.             XtNfromHoriz, vport,
  761.             XtNtop, XtChainTop,
  762.             XtNbottom, XtChainTop,
  763.             NULL);
  764.     vport = XtVaCreateManagedWidget("vport",
  765.             viewportWidgetClass, form,
  766.             XtNuseBottom, True,
  767.             XtNuseRight, True,
  768.             XtNforceBars, True,
  769.             XtNallowHoriz, False,
  770.             XtNallowVert, True,
  771.             XtNfromHoriz, vport,
  772.             XtNfromVert, label,
  773.             XtNtop, XtChainTop,
  774.             NULL);
  775.     arg->point = XtVaCreateManagedWidget("point",
  776.                 listWidgetClass, vport,
  777.                 XtNverticalList, True,
  778.                 XtNforceColumns, True,
  779.                 XtNdefaultColumns, 1,
  780.                 XtNnumberStrings, 0,
  781.                 NULL);
  782.  
  783.     /*
  784.     **  The text area and buttons
  785.     */
  786.     form = XtVaCreateManagedWidget("form2",
  787.             formWidgetClass, pane,
  788.             XtNborderWidth, 0,
  789.             NULL);
  790.     form2 = XtVaCreateManagedWidget("subForm",
  791.             formWidgetClass, form,
  792.             XtNborderWidth, 0,
  793.             XtNtop, XtChainTop,
  794.             XtNbottom, XtChainTop,
  795.             NULL);
  796.  
  797.     selectLabel = XtVaCreateWidget("pointLabel",
  798.             labelWidgetClass, form2,
  799.             XtNborderWidth, 0,
  800.             XtNleft, XtChainLeft,
  801.             XtNright, XtChainLeft,
  802.             NULL);
  803.  
  804.     XtAppAddActions(XtWidgetToApplicationContext(form2), &pointAct, 1);
  805.  
  806.     arg->pointSelect = XtVaCreateWidget("pointSelect",
  807.             asciiTextWidgetClass, form2,
  808.             XtNleft, XtChainLeft,
  809.             XtNright, XtChainRight,
  810.             XtNfromHoriz, selectLabel,
  811.             XtNeditType, XawtextEdit,
  812.             XtNwrap, XawtextWrapNever,
  813.             XtNlength, 8,
  814.             XtNtranslations, 
  815.                 XtParseTranslationTable("#override\n\
  816.                     <Key>Return: point-size-ok()\n\
  817.                     <Key>Linefeed: point-size-ok()\n\
  818.                     Ctrl<Key>M: point-size-ok()\n\
  819.                     Ctrl<Key>J: point-size-ok()\n"),
  820.             NULL);
  821.  
  822.     label = XtVaCreateManagedWidget("fontNameLabel",
  823.             labelWidgetClass, form,
  824.             XtNborderWidth, 0,
  825.             XtNfromVert, form2,
  826.             XtNleft, XtChainLeft,
  827.             XtNtop, XtChainTop,
  828.             XtNbottom, XtChainTop,
  829.             NULL);
  830.     arg->fontName = XtVaCreateManagedWidget("fontName",
  831.             asciiTextWidgetClass, form,
  832.             XtNfromVert, form2,
  833.             XtNfromHoriz, label,
  834.             XtNallowResize, True,
  835.             XtNstring, "",
  836.             XtNtop, XtChainTop,
  837.             XtNbottom, XtChainTop,
  838.             XtNdisplayCaret, False,
  839.             NULL);
  840.  
  841.     arg->text = XtVaCreateManagedWidget("text",
  842.             asciiTextWidgetClass, form,
  843.             XtNfromVert, arg->fontName,
  844.             XtNallowResize, True,
  845.             XtNstring, "",
  846.             XtNtop, XtChainTop,
  847.             XtNbottom, XtChainBottom,
  848.             XtNdisplayCaret, False,
  849.             NULL);
  850.  
  851.     okButton = XtVaCreateManagedWidget("ok",
  852.             commandWidgetClass, form,
  853.             XtNfromVert, arg->text,
  854.             XtNtop, XtChainBottom,
  855.             XtNbottom, XtChainBottom,
  856.             XtNright, XtChainLeft,
  857.             XtNleft, XtChainLeft,
  858.             NULL);
  859.     applyButton = XtVaCreateManagedWidget("apply",
  860.             commandWidgetClass, form,
  861.             XtNfromVert, arg->text,
  862.             XtNfromHoriz, okButton,
  863.             XtNtop, XtChainBottom,
  864.             XtNbottom, XtChainBottom,
  865.             XtNright, XtChainLeft,
  866.             XtNleft, XtChainLeft,
  867.             NULL);
  868.  
  869.     doneButton = XtVaCreateManagedWidget("done",
  870.             commandWidgetClass, form,
  871.             XtNfromVert, arg->text,
  872.             XtNfromHoriz, applyButton,
  873.             XtNtop, XtChainBottom,
  874.             XtNbottom, XtChainBottom,
  875.             XtNleft, XtChainLeft,
  876.             XtNright, XtChainLeft,
  877.             XtNleft, XtChainLeft,
  878.             NULL);
  879.  
  880.     /*
  881.     **  Init the world
  882.     */
  883.     arg->paint = paint;
  884.     arg->namesStorage = XListFonts(XtDisplay(shell), "*", 32767, &arg->number),
  885.     arg->names = chop(&arg->number, arg->namesStorage);
  886.     arg->expectFlag = False;
  887.     match(arg);
  888.  
  889.     if (haveScalable) {
  890.         Widget    list[2];
  891.         list[0] = selectLabel;
  892.         list[1] = arg->pointSelect;
  893.         XtManageChildren(list, 2);
  894.     } else {
  895.         XtVaSetValues(form2, XtNwidth, 1, XtNheight, 1, NULL);
  896.     }
  897.  
  898.     XtAddEventHandler(arg->spacing, ButtonPressMask|ButtonReleaseMask, False, expectCallback, (XtPointer)arg);
  899.     XtAddEventHandler(arg->family, ButtonPressMask|ButtonReleaseMask, False, expectCallback, (XtPointer)arg);
  900.     XtAddEventHandler(arg->weight, ButtonPressMask|ButtonReleaseMask, False, expectCallback, (XtPointer)arg);
  901.     XtAddEventHandler(arg->point, ButtonPressMask|ButtonReleaseMask, False, expectCallback, (XtPointer)arg);
  902.  
  903.     XtAddCallback(arg->spacing, XtNcallback, listCallback, (XtPointer)arg);
  904.     XtAddCallback(arg->family, XtNcallback, listCallback, (XtPointer)arg);
  905.     XtAddCallback(arg->weight, XtNcallback, listCallback, (XtPointer)arg);
  906.     XtAddCallback(arg->point, XtNcallback, listCallback, (XtPointer)arg);
  907.  
  908.     XtAddCallback(okButton, XtNcallback, okCallback, (XtPointer)arg);
  909.     XtAddCallback(applyButton, XtNcallback, applyCallback, (XtPointer)arg);
  910.     XtAddCallback(doneButton, XtNcallback, closeCallback, (XtPointer)arg);
  911.     AddDestroyCallback(shell, 
  912.         (void (*)(Widget, void *, XEvent *))closeCallback, arg);
  913.     
  914.     XtPopup(shell, XtGrabNone);
  915.     StateSetBusyWatch(False);
  916.  
  917.     theArg = arg;
  918. }
  919.